<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2024/4/23
 * Time: 15:19
 */

namespace app\logic\index\tool;


use app\common\lib\Common;
use app\common\lib\Puppeteer;
use app\common\lib\RedisQueue;
use app\common\lib\TencentAsr;
use app\common\lib\TencentCos;
use app\exception\IndexException;
use app\logic\BaseLogic;
use app\model\ai\BotGenerateImageStyleModel;
use app\model\tool\ToolArticleChangeCommandModel;
use app\model\tool\UserToolArticleModel;
use app\model\tool\UserToolVideoModel;
use support\Db;

class ToolManageLogic extends BaseLogic
{
    protected $model;

    protected static $instance;

    public function __construct()
    {
        parent::__construct();
        $this->model = \app\model\tool\ToolManageModel::getInstance();
    }

    public static function getInstance()
    {
//        if(is_object(self::$instance)){
//            return self::$instance;
//        }

        return  new self();
    }

    public function getList($param)
    {
        $where = [
            'isdel'=>0,
            'status'=>1,
        ];
        $fields = ['id','name','main_image','charge_type','point_nums','tag_icon','link'];
        $order = ['sort', 'desc'];

        $list =  $this->model->index($where, $fields, $order);

        return $list;
    }

    public function getDetail($param)
    {
        $first = $this->model->find($param['tool_id']);
        if($first==false){
            throw new IndexException(4020,'工具不存在');
        }

        return $first;
    }

    protected function checkAuth($param)
    {
        $first = $this->model->find($param['tool_id']);
        if($first==false){
            throw new IndexException(4020,'工具不存在');
        }
        if($first['charge_type']=='2'){
            $user = $this->checkIsVip();
            if($user==false || $user['is_vip']==0){
                throw new IndexException(4020,'VIP会员才能使用');
            }
        }elseif($first['charge_type']=='3'){
            $this->consumePoint(['consume_point'=>$first['point_nums']]);
        }

        return $first;
    }

    public function collectVideo($param)
    {
        $tool = $this->checkAuth($param);

        $videoLink = Puppeteer::getInstance()->getVideoLink($param['content']);
        $name = substr(md5(Common::getRequestId()),-20);
        $filePath = runtime_path('tool/'.date('ymd').'/'.$name.'.mp4');
        Common::mkdirs(dirname($filePath));
        $res = file_put_contents($filePath,file_get_contents($videoLink));
        if($res==false){
            throw new IndexException(4020,'视频提取失败');
        }
        if(is_file($videoLink)){
            @unlink($videoLink);
        }
        $res = TencentCos::getInstance()->uploadLocalFile($filePath,'tool/video');
        $videoLink = 'https://'.$res['Location'];
        @unlink($filePath);

        try{
            Db::connection('mysql')->beginTransaction();
            $insert = [
                'user_sn'=>request()->curUserId,
                'content'=>$param['content']??'',
                'video_url'=>$param['video_url']??'',
                'video_link'=>$videoLink,
                'video_word'=>'',
                'type'=>'1',
            ];
            $id = UserToolVideoModel::getInstance()->insertGetId($insert);

            if($tool['charge_type']=='3'){
                $ponintParam = [
                    'source_table'=>UserToolVideoModel::getInstance()->getTable(),
                    'sourceid'=>$id,
                ];
                $this->insertConsumePoint($tool['point_nums'],$ponintParam,4);
            }

            Db::connection('mysql')->commit();
        }catch (IndexException $e){
            Db::connection('mysql')->rollBack();
            throw $e;
        }

        return ['video_link'=>$videoLink];
    }

    public function collectVideoAndGetWord($param)
    {
        $tool = $this->checkAuth($param);

        if(!empty($param['content'])){
            $videoLink = Puppeteer::getInstance()->getVideoLink($param['content']);
            $name = substr(md5(Common::getRequestId()),-20);
            $filePath = runtime_path('tool/'.date('ymd').'/'.$name.'.mp4');
            Common::mkdirs(dirname($filePath));
            $res = file_put_contents($filePath,file_get_contents($videoLink));
            if($res==false){
                throw new IndexException(4020,'视频提取失败');
            }
            if(is_file($videoLink)){
                @unlink($videoLink);
            }
            $res = TencentCos::getInstance()->uploadLocalFile($filePath,'tool/video');
            $videoLink = 'https://'.$res['Location'];
            @unlink($filePath);
        }else{
            $videoLink = $param['video_url'];
        }

        $res = TencentAsr::getInstance()->createRecTask($videoLink);

        $content = '';
        $startTime = time();
        while (true){
            $result = TencentAsr::getInstance()->describeTaskStatus($res['Data']['TaskId']);
            if(!empty($result['Data']['Status']) && $result['Data']['Status']==2){
                if(!empty($result['Data']['Result'])){
                    $content = trim(mb_substr($result['Data']['Result'],18));
                    $content = preg_replace(['/\[[\d|,|:|.]+\]/'],'',$content);
                }
                $replaceStr =  ['`','~','!','@','#','$','^','&','*','(',')','=','|','{','}','\\',':',';',',','[',']','.','+','-','_',
                                '<','>','《','》','/','?','！','￥','……','（','）','――','|','【','】',
                                '‘','；','：','”','“','。','，','、','？',', ','\'','"','’',' '];
                $content = str_replace($replaceStr, "\n",$content);
                try{
                    Db::connection('mysql')->beginTransaction();
                    $insert = [
                        'user_sn'=>request()->curUserId,
                        'content'=>$param['content']??'',
                        'video_url'=>$param['video_url']??'',
                        'video_link'=>$videoLink,
                        'video_word'=>$content,
                        'type'=>'2',
                    ];
                    $id = UserToolVideoModel::getInstance()->insertGetId($insert);

                    if($tool['charge_type']=='3'){
                        $ponintParam = [
                            'source_table'=>UserToolVideoModel::getInstance()->getTable(),
                            'sourceid'=>$id,
                        ];
                        $this->insertConsumePoint($tool['point_nums'],$ponintParam,4);
                    }

                    Db::connection('mysql')->commit();
                }catch (IndexException $e){
                    Db::connection('mysql')->rollBack();
                    throw $e;
                }

                return ['content'=>$content];
            }elseif(!empty($result['Data']['Status']) && $result['Data']['Status']==3){
                throw new IndexException(4020,'视频提取文字失败');
            }

            if((time()-$startTime)>60){
                throw new IndexException(4020,'视频提取文字超时');
            }
        }
    }

    public function getArticleModelList($param)
    {
        $where = [
            'isdel'=>0,
            'status'=>1
        ];
        $field = ['id','name','command_content'];
        $order = ['sort','desc'];
        $data = ToolArticleChangeCommandModel::getInstance()->index($where,$field,$order);

        return $data;
    }

    public function articleContentChange($param)
    {
        $tool = $this->checkAuth($param);

        $strLen = mb_strlen($param['content']);
        if($strLen<100 || $strLen>3000){
            throw new IndexException(4020,'内容文字字数范围100-3000');
        }

        $first = ToolArticleChangeCommandModel::getInstance()->find($param['model_id']);
        if($first==false){
            throw new IndexException(4020,'风格不存在');
        }

        if(strpos($first['command_content'],'@content')===false){
            $first['command_content'] .= "\n @content";
        }
        $content = Common::generatedContent($param['content'], $first['command_content']);

        try{
            Db::connection('mysql')->beginTransaction();
            $insert = [
                'user_sn'=>request()->curUserId,
                'content'=>$param['content']??'',
                'analyze_content'=>$content,
                'type'=>'1',
                'model_id'=>$param['model_id'],
                'command_content'=>$first['command_content'],
                'status'=>1,
            ];
            $id = UserToolArticleModel::getInstance()->insertGetId($insert);

            if($tool['charge_type']=='3'){
                $ponintParam = [
                    'source_table'=>UserToolArticleModel::getInstance()->getTable(),
                    'sourceid'=>$id,
                ];
                $this->insertConsumePoint($tool['point_nums'],$ponintParam,4);
            }

            Db::connection('mysql')->commit();
        }catch (IndexException $e){
            Db::connection('mysql')->rollBack();
            throw $e;
        }

        return ['content'=>$content];
    }

    public function articleContentPart($param)
    {
        $tool = $this->checkAuth($param);

        $strLen = mb_strlen($param['content']);
        if($strLen<100 || $strLen>3000){
            throw new IndexException(4020,'内容文字字数范围100-3000');
        }


        $command = getAiCommand('content_parts_ai_command');
        if(strpos($command,'@content')===false){
            $command .= "\n @content";
        }
        $content = Common::generatedContent($param['content'], $command);

        try{
            Db::connection('mysql')->beginTransaction();
            $insert = [
                'user_sn'=>request()->curUserId,
                'content'=>$param['content']??'',
                'analyze_content'=>$content,
                'type'=>'2',
                'model_id'=>0,
                'command_content'=>$command,
                'status'=>1,
            ];
            $id = UserToolArticleModel::getInstance()->insertGetId($insert);

            if($tool['charge_type']=='3'){
                $ponintParam = [
                    'source_table'=>UserToolArticleModel::getInstance()->getTable(),
                    'sourceid'=>$id,
                ];
                $this->insertConsumePoint($tool['point_nums'],$ponintParam,4);
            }

            Db::connection('mysql')->commit();
        }catch (IndexException $e){
            Db::connection('mysql')->rollBack();
            throw $e;
        }

        return ['content'=>$content];
    }

    public function getArticleGenerateLog($param)
    {
        $where = [
            'user_sn'=>request()->curUserId,
            'type'=>$param['type']?:1,
        ];
        $field = ['id','user_sn','content','analyze_content','model_id','status','created_at','type'];
        $order = ['id','desc'];
        $data = UserToolArticleModel::getInstance()->index($where,$field,$order);
        $modelMap = $this->getListMapById(ToolArticleChangeCommandModel::getInstance(),$data['data']->toArray(),'model_id','id');
        $modelMap2 = $this->getListMapById(BotGenerateImageStyleModel::getInstance(),$data['data']->toArray(),'model_id','id');
        foreach($data['data'] as $val){
            if($val['type']==1){
                $val['model_name'] = isset($modelMap[$val['model_id']]) ? $modelMap[$val['model_id']]['name'] : '';
            }elseif($val['type']==6){
                $val['model_name'] = isset($modelMap2[$val['model_id']]) ? $modelMap2[$val['model_id']]['name'] : '';
            }else{
                $val['model_name'] = '';
            }
        }
        return $data;
    }

    public function articleHeadChange($param)
    {
        $tool = $this->checkAuth($param);

        $strLen = mb_strlen($param['content']);
        if($strLen<100 || $strLen>3000){
            throw new IndexException(4020,'内容文字字数范围100-3000');
        }

        $command = getAiCommand('article_head_analyze_command');

        if(strpos($command,'@content')===false){
            $command .= "\n @content";
        }
        $content = Common::generatedContent($param['content'], $command);

        try{
            Db::connection('mysql')->beginTransaction();
            $insert = [
                'user_sn'=>request()->curUserId,
                'content'=>$param['content']??'',
                'analyze_content'=>$content,
                'type'=>'3',
                'command_content'=>$command,
                'status'=>1,
            ];
            $id = UserToolArticleModel::getInstance()->insertGetId($insert);

            if($tool['charge_type']=='3'){
                $ponintParam = [
                    'source_table'=>UserToolArticleModel::getInstance()->getTable(),
                    'sourceid'=>$id,
                ];
                $this->insertConsumePoint($tool['point_nums'],$ponintParam,4);
            }

            Db::connection('mysql')->commit();
        }catch (IndexException $e){
            Db::connection('mysql')->rollBack();
            throw $e;
        }

        return ['content'=>$content];
    }

    public function articleKeywordGenerate($param)
    {
        $tool = $this->checkAuth($param);

        $strLen = mb_strlen($param['content']);
        if($strLen<100 || $strLen>3000){
            throw new IndexException(4020,'内容文字字数范围100-3000');
        }

        $command = getAiCommand('keyword_generater_command');

        if(strpos($command,'@content')===false){
            $command .= "\n @content";
        }
        $content = Common::generatedContent($param['content'], $command);
        $content = str_replace(['、','，'],',',$content);

        try{
            Db::connection('mysql')->beginTransaction();
            $insert = [
                'user_sn'=>request()->curUserId,
                'content'=>$param['content']??'',
                'analyze_content'=>$content,
                'type'=>'4',
                'command_content'=>$command,
                'status'=>1,
            ];
            $id = UserToolArticleModel::getInstance()->insertGetId($insert);

            if($tool['charge_type']=='3'){
                $ponintParam = [
                    'source_table'=>UserToolArticleModel::getInstance()->getTable(),
                    'sourceid'=>$id,
                ];
                $this->insertConsumePoint($tool['point_nums'],$ponintParam,4);
            }

            Db::connection('mysql')->commit();
        }catch (IndexException $e){
            Db::connection('mysql')->rollBack();
            throw $e;
        }

        return ['content'=>$content];
    }

    public function saveToolGenerateContent($param)
    {
        $tool = $this->checkAuth($param);

        try{
            Db::connection('mysql')->beginTransaction();
            $insert = [
                'user_sn'=>request()->curUserId,
                'content'=>$param['content']??'',
                'analyze_content'=>$param['analyze_content'],
                'type'=>$param['type']??0,
                'command_content'=>'',
                'model_id'=>$param['model_id']??0,
                'status'=>1,
            ];
            $id = UserToolArticleModel::getInstance()->insertGetId($insert);

            if($tool['charge_type']=='3'){
                $ponintParam = [
                    'source_table'=>UserToolArticleModel::getInstance()->getTable(),
                    'sourceid'=>$id,
                ];
                $this->insertConsumePoint($tool['point_nums'],$ponintParam,4);
            }

            Db::connection('mysql')->commit();
        }catch (IndexException $e){
            Db::connection('mysql')->rollBack();
            throw $e;
        }

        return $id;
    }

    public function getBotImageStyleList($param)
    {
        $data = BotGenerateImageStyleModel::getInstance()->getWhere(['isdel'=>0])->orderBy('id','desc')->get()->toArray();
        $data = $this->unsetCommonFields($data);

        return ['data'=>$data];
    }

    public function submitToolContent($param)
    {
        $tool = $this->checkAuth($param);
        $id = 0;
        switch ($param['tool_type']){
            case 'video_water':
            case 'video_word':
                $insert = [
                    'user_sn'=>request()->curUserId,
                    'content'=>$param['content']??'',
                    'video_url'=>$param['video_url']??'',
                    'video_link'=>'',
                    'video_word'=>'',
                    'type'=>$param['tool_type']=='video_water'?1:2,
                ];
                $id = UserToolVideoModel::getInstance()->insertGetId($insert);
                break;
            case 'article_change':
            case 'article_part':
            case 'article_head_change':
            case 'article_keyword':
                $strLen = mb_strlen($param['content']);
                if($strLen<300 || $strLen>6000){
                    throw new IndexException(4020,'内容文字字数范围300-6000');
                }

                $toolTypeMap = [
                    'article_change'=>1,
                    'article_part'=>2,
                    'article_head_change'=>3,
                    'article_keyword'=>4,
                ];
                $insert = [
                    'user_sn'=>request()->curUserId,
                    'content'=>$param['content']??'',
                    'analyze_content'=>'',
                    'type'=>$toolTypeMap[$param['tool_type']]??1,
                    'model_id'=>!empty($param['model_id'])?$param['model_id']:0,
                    'command_content'=>'',
                ];
                $id = UserToolArticleModel::getInstance()->insertGetId($insert);
                break;
        }

        //生成唯一的请求id
        $requestId = Common::getRequestId();

        // 队列名
        $queue = 'aiGenerateContent';
        // 数据，可以直接传数组，无需序列化
        $data = ['requestid' => $requestId, 'id' => $id, 'tool_id' => $tool['id'], 'tool_type' => $param['tool_type']];
        // 投递消息
        RedisQueue::getInstance()->sendQueue($queue, $data);

        return ['requestid' => $requestId, 'id' => $id, 'tool_type' => $param['tool_type']];
    }

    public function getToolAnalyzeResult($param)
    {
        switch ($param['tool_type']){
            case 'video_water':
                $first = UserToolVideoModel::getInstance()->find($param['id']);
                if($first==false){
                    throw new IndexException(4020,'数据不存在');
                }
                return ['content' => $first['video_link'], 'status' => $first['status'], 'message' => $first['message']];
            case 'video_word':
                $first = UserToolVideoModel::getInstance()->find($param['id']);
                if($first==false){
                    throw new IndexException(4020,'数据不存在');
                }
                return ['content' => $first['video_word'], 'status' => $first['status'], 'message' => $first['message']];
            case 'article_change':
            case 'article_part':
            case 'article_head_change':
            case 'article_keyword':
            $first = UserToolArticleModel::getInstance()->find($param['id']);
            if($first==false){
                throw new IndexException(4020,'数据不存在');
            }
            return ['content' => $first['analyze_content'], 'status' => $first['status'], 'message' => $first['message']];
        }
    }
}